package com.darwin.darwinImage.jpg
{
//	import cmodule.jpeg32.CLibInit;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BitmapDataChannel;
	import flash.display.Loader;
	import flash.display.Shader;
	import flash.display.ShaderJob;
	import flash.display.Shape;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.filters.ShaderFilter;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.utils.ByteArray;
	
	import mx.graphics.codec.JPEGEncoder;
	
	
	/**
	 *	解码完成事件 
	 */
	[Event(name="complete",type="flash.events.Event")]
	/**
	 * 带alpha通道的32位jpeg格式图像编码/解码类
	 * @author Roland
	 */
	public class JPEG32 extends EventDispatcher
	{
	/*	[Embed (source="embed/Jpeg32AlphaRecover.pbj", mimeType="application/octet-stream")]
		private static var shaderCode:Class;*/
		/**
		 *	解码完成后的bitmapData，如果未进行过解码则为null 
		 */
		public var bitmapData:BitmapData;
		
		private var _quality:int;
		private var _alphaLv:int;
		/**
		 * 实例化JPEG32编码/解码类
		 * @param quality 编码质量 1～100
		 * @param alphaLv alpha通道分级 16或256 (此参数在编码和解码时必须保持一致)
		 * 
		 */
		public function JPEG32(quality:int = 70,alphaLv:int = 16)
		{
			_quality = quality;
			_alphaLv = alphaLv;
		}
		
		/**
		 *	 将传入的bitmapData编码为携带alpha通道的Jpeg格式 
		 * @param bitmapData 要编码的位图数据
		 * @return 
		 * 
		 */
		public function encode(bitmapData:BitmapData):ByteArray
		{
			var $encoder:JPEGEncoder = new JPEGEncoder(_quality);
			var $aBlock:ByteArray = getAlphaDataBlock(bitmapData,_alphaLv);
			var $aBlockLength:uint = $aBlock.length;			
			var $bBlock:ByteArray = $encoder.encode(bitmapData);
			var $fBlock:ByteArray = new ByteArray();
			
			$fBlock.position = 0;
			$fBlock.writeUnsignedInt($aBlockLength);//写入alpha数据块长度
			$fBlock.writeBytes($aBlock,0,$aBlock.length);//写入alpha数据块
			$fBlock.writeBytes($bBlock,0,$bBlock.length);//写入bitmap数据块
			return $fBlock;
		}
		
		public var other:Object;
		/**
		 *	将传入的携带alpha通道的Jpeg二进制数据解码为bitmapData 
		 * <li>解码完成后将抛出Event.COMPLETE事件,还原出的bitmapData携带在e.target.bitmapData属性中</li>
		 * @param bytes 要解码的二进制数据
		 * 
		 */
		public function decode(bytes:ByteArray,other:Object = null):void
		{
			this.other = other;
			var $fBlock:ByteArray = bytes;
			$fBlock.position = 0;
			var $aLength:uint  = $fBlock.readUnsignedInt();
			var $aBlock:ByteArray = new ByteArray();
			var $bBlock:ByteArray = new ByteArray();
			$fBlock.readBytes($aBlock,0,$aLength);
			$fBlock.readBytes($bBlock,0);
			
			//解析位图
			var $loader:Loader = new Loader();
			$loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoadComplete);
			$loader.loadBytes($bBlock);
			function onLoadComplete(event:Event):void
			{
				$loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,onLoadComplete);
				var $bitmapData:BitmapData =  ($loader.content as Bitmap).bitmapData;
				bitmapData = writeAlphaToBitmapData($aBlock,$bitmapData,_alphaLv);//合并alpha通道
				dispatchEvent(new Event(Event.COMPLETE));
			}		
		}
		
		
		/**
		 *	提取图像alpha通道数据块
		 * @param source 源图像数据
		 * @param alphaLevel alpha通道分级，只接受16或者256
		 * @return 
		 * 
		 */
		private static function getAlphaDataBlock(source:BitmapData,alphaLevel:int = 16):ByteArray
		{
			var alphaBitmapData:BitmapData = new BitmapData(source.width,source.height,true,0);
			alphaBitmapData.copyChannel(source,source.rect,new Point(),BitmapDataChannel.ALPHA,BitmapDataChannel.ALPHA);
			var bytes:ByteArray = new ByteArray();
			bytes.position = 0;
			bytes.writeUTF("jpeg32");//写入新格式标记
			bytes.writeBytes(alphaBitmapData.getPixels(alphaBitmapData.rect));
			/*for (var x:int = 0; x < source.width; x++) 
			{
				for (var y:int = 0; y < source.height; y++) 
				{
					var pixel:uint=source.getPixel32(x,y);
					var a:uint = pixel >>> 24;//取alpha通道
					if(alphaLevel<=16)
					{
						var ca:uint = a>>4;//均衡压缩，截去低8位
						bytes.writeByte(ca);
					}else{
						bytes.writeByte(a);
					}
				}
			}*/
			bytes.compress();//二次压缩
			return bytes;
		}
		
		/**
		 *	将alpha数据块写入bitmapData 
		 * @param alphaDataBlock alpha通道数据块
		 * @param bitmapData 位图数据
		 * @param alphaLevel alpha通道分级，只接受16或者256
		 * @return 
		 * 
		 */
		private static function writeAlphaToBitmapData(alphaDataBlock:ByteArray,bitmapData:BitmapData,alphaLevel:int = 16):BitmapData
		{
			var retBitmapData:BitmapData;
			alphaDataBlock.uncompress();//解压缩
			alphaDataBlock.position = 0;
			
			if(alphaDataBlock.length >= 8 && alphaDataBlock.readUTF() == "jpeg32")
			{
				var alphaBitmapData:BitmapData =  new BitmapData(bitmapData.width,bitmapData.height,true,0);
				retBitmapData = new BitmapData(bitmapData.width,bitmapData.height,true,0);
				alphaBitmapData.setPixels(retBitmapData.rect,alphaDataBlock);
				retBitmapData.copyPixels(bitmapData,bitmapData.rect,new Point(),alphaBitmapData,new Point(),true);
			}else{
				alphaDataBlock.position = 0;
				retBitmapData = new BitmapData(bitmapData.width,bitmapData.height,true,0);
				retBitmapData.lock();
				for (var x:int = 0; x < retBitmapData.width; x++) 
				{
					for (var y:int = 0; y < retBitmapData.height; y++) 
					{
						var a:uint = alphaDataBlock.readByte() & 0xff;
						if(a != 0)
						{
							if(alphaLevel<=16)
							{
								a = (a | (a << 4));//恢复均衡压缩
							}
							var apix:uint = ((a << 24) & 0xff000000)
							var pixel:uint = bitmapData.getPixel(x,y);
							var pixel32:uint = pixel | apix;
							retBitmapData.setPixel32(x,y,pixel32);
						}
					}	
				}
				retBitmapData.unlock();
			}
			return retBitmapData;
			
			
		}
		
		/*private static function getAlphaBitmapData(alphaInfo:ByteArray,bitmapData:BitmapData,alphaLevel:int = 16):BitmapData
		{
			var bitmapDataBytes:ByteArray = bitmapData.getPixels(bitmapData.rect);
			var ab:BitmapData =  new BitmapData(bitmapData.width,bitmapData.height,true,0);
			var pbBytes:ByteArray = rebuildAlphaBytes(alphaInfo,alphaLevel);
			var shader:Shader = new Shader(new shaderCode());
			shader.data.aBlock.width = bitmapData.height;//alpha数据块高宽和原图相反
			shader.data.aBlock.height = bitmapData.width;//
			shader.data.aBlock.input = pbBytes;
			shader.data.src.input = bitmapData;
			
			var shape:Shape = new Shape();
			shape.graphics.beginShaderFill(shader);
			shape.graphics.drawRect(0,0,bitmapData.width,bitmapData.height);
			shape.graphics.endFill();
			ab.draw(shape);
			return ab;
		}*/
		
		/**
		 *	将alpha通道信息重建为pixel bender可识别的二进制流 
		 * @param bytes
		 * @return 
		 * 
		 */
		/*private static function rebuildAlphaBytes(bytes:ByteArray,alphaLevel:int = 16):ByteArray
		{
			bytes.position = 0;
			var pbBytes:ByteArray = new ByteArray();
			var zeroBytes:ByteArray = new ByteArray();
			zeroBytes.writeFloat(0);//r
			zeroBytes.writeFloat(0);//g
			zeroBytes.writeFloat(0);//b
			while(bytes.bytesAvailable)
			{
				var a:int = bytes.readByte();
				if(alphaLevel<=16)
				{
					a = (a | (a << 4));//恢复均衡压缩
				}
				pbBytes.writeBytes(zeroBytes,0,zeroBytes.length);
				pbBytes.writeFloat(a/256);//a
			}
			return pbBytes;
		}*/
	}
}